#include "Sigup.h"
#include "CryptoUtil.h"
#include <workflow/MySQLResult.h>
#include <map>
#include <string>
#include <iostream>
using std::map;
using std::string;
using namespace protocol;
using namespace wfrest;

Sigup::Sigup(wfrest::HttpServer & server)
:m_server(server)
{}

void Sigup::start(){
    signup_module();
}

struct Context{
    HttpResp* resp;
    string username;
    string password;
};

void doRegisterCallback(WFMySQLTask * mysqlTask){
    Context * context = static_cast<Context*>(series_of(mysqlTask)->get_context());
    if(mysqlTask->get_state() !=WFT_STATE_SUCCESS){
        context->resp->String("mysqlTask failed");
        return;
    }

    MySQLResultCursor cursor(mysqlTask->get_resp());

    if(cursor.get_cursor_status()==MYSQL_PACKET_ERROR){
        context->resp->String("error");
        return ;
    }

    if(cursor.get_cursor_status()==MYSQL_STATUS_OK){
        context->resp->String("SUCCESS");
    }
}

void Sigup::signup_module(){
    m_server.POST("/user/signup",[](const HttpReq* req, HttpResp* resp,SeriesWork* series){
        string username;
        string password;
        const map<string, string> &  prams = req->form_kv();
        for(const auto & [key,value]:prams){
            if(key == "username"){
                username = value;
            }
            if(key == "password"){
                password = value;
            }
        }

        #ifdef DEBUG
            std::cout<<username<<"\n";
            std::cout<<password<<"\n";
        #endif

        string salt = CryptoUtil::generate_salt();
        string encode_password = CryptoUtil::hash_password(password,salt);
        string sql = "insert into tbl_users (username , password, salt) values ('"+username+"','"+encode_password +"','"+salt+"');";
        WFMySQLTask * mysqltask = WFTaskFactory::create_mysql_task("mysql://root:123@localhost/newCloudDisk",3,doRegisterCallback);
        mysqltask->get_req()->set_query(sql);
        
        Context * ctx = new Context{resp,{},{}};
        series->set_context(ctx);
        series->set_callback([ctx](const SeriesWork *){
            delete ctx;
        });
        
        series->push_back(mysqltask);
    });    
}